package com.rn_demo3.util;

import android.content.Context;
import android.util.Base64;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import okio.Utf8;

public class Crypt {
    public static final String LOG_TAG = "Crypt";
    private SecretKeySpec secretKeySpec;
    private IvParameterSpec ivParameterSpec;
    private Cipher cipher;

    private byte[] bytes;

    public Crypt(Context context, String pwd) {
        try {
            secretKeySpec = new SecretKeySpec(pwd.getBytes(), "AES");
//            secretKeySpec = getSecretKey(pwd);
            ivParameterSpec = new IvParameterSpec(new byte[16]);
            cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件AES加密
     * @param file1 原文件路径
     * @param file2 加密文件存放路径
     * @return 是否成功
     */
    public boolean fileEn(File file1, File file2){
        try {
            cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,ivParameterSpec);
        }catch (Exception e){
            return false;
        }
        try (CipherInputStream cipherInputStream = new CipherInputStream(new FileInputStream(file1),cipher);
             BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file2))){
            bytes = new byte[1024];
            int len;
            while ((len=cipherInputStream.read(bytes))!=-1){
                bufferedOutputStream.write(bytes,0,len);
                bufferedOutputStream.flush();
            }
            return true;
        }catch (Exception e){
            e.printStackTrace();
            file2.delete();
            return false;
        }
    }

    /**
     * 文件AES解密
     * @param file1 加密文件路径
     * @param file2 原文件存放路径
     * @return 是否成功
     */
    public boolean fileDe(File file1, File file2) {
        try {
            cipher.init(Cipher.DECRYPT_MODE,secretKeySpec);
        }catch (Exception e){
            return false;
        }
        try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file1));

             CipherOutputStream cipherOutputStream = new CipherOutputStream(new FileOutputStream(file2), cipher)) {
            bytes = new byte[1024];

            int len;
            while ((len = bufferedInputStream.read(bytes)) != -1) {
                cipherOutputStream.write(bytes, 0, len);
                cipherOutputStream.flush();
            }

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            file2.delete();
            return false;
        }
    }



    /**
     * 字符串AES加密
     * @param str 原文
     * @return 密文
     */
    public String textEn(String str){
        try {
            cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,ivParameterSpec);
            return Base64.encodeToString(cipher.doFinal(str.getBytes()),Base64.NO_WRAP);
        }catch (Exception e){
            return "";
        }
    }

    /**
     * 字符串AES解密
     * @param str 密文
     * @return 原文
     */
    public String textDe(String str){
        try {
            cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,ivParameterSpec);
            return new String(cipher.doFinal(Base64.decode(str,Base64.NO_WRAP)));
        }catch (Exception e){
            return "";
        }
    }

    /**
     * AES 的 密钥长度，32 字节，范围：16 - 32 字节
     */
    public static final int SECRET_KEY_LENGTH = 32;
    /**
     * 秘钥长度不足 16 个字节时，默认填充位数
     */
    private static final String DEFAULT_VALUE = "0";
    /**
     * 使用密码获取 AES 秘钥
     */
    public static SecretKeySpec getSecretKey(String secretKey) {
        secretKey = toMakeKey(secretKey, SECRET_KEY_LENGTH, DEFAULT_VALUE);
        return new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
    }

    /**
     * 如果 AES 的密钥小于 {@code length} 的长度，就对秘钥进行补位，保证秘钥安全。
     *
     * @param secretKey 密钥 key
     * @param length    密钥应有的长度
     * @param text      默认补的文本
     * @return 密钥
     */
    private static String toMakeKey(String secretKey, int length, String text) {
        // 获取密钥长度
        int strLen = secretKey.length();
        // 判断长度是否小于应有的长度
        if (strLen < length) {
            // 补全位数
            StringBuilder builder = new StringBuilder();
            // 将key添加至builder中
            builder.append(secretKey);
            // 遍历添加默认文本
            for (int i = 0; i < length - strLen; i++) {
                builder.append(text);
            }
            // 赋值
            secretKey = builder.toString();
        }
        return secretKey;
    }


    public void recovery(){
        secretKeySpec = null;
        ivParameterSpec = null;
        cipher = null;
        bytes = null;
        System.gc();
    }
}
